#!/usr/bin/env python
#coding:utf-8
import sys
import os
import logging
import time

import cyclone.web
from twisted.python import log
from twisted.internet import reactor
from beaker.cache import CacheManager
from beaker.util import parse_cache_config_options
from mako.lookup import TemplateLookup
from sqlalchemy.orm import scoped_session, sessionmaker

from toughadmin.tools import utils
from toughadmin.tools.permit import permit
from toughadmin.console import models
from toughadmin.console.admin import handlers


class Application(cyclone.web.Application):
    def __init__(self,**kwargs):

        server = kwargs.pop("server")
        
        settings = dict(
            cookie_secret="12oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=",
            login_url="/login",
            template_path=os.path.join(os.path.dirname(__file__), "admin/views"),
            static_path=os.path.join(os.path.dirname(__file__), "static"),
            xsrf_cookies=True,
            api_secret=kwargs.get("api_secret"),
            backup_path=kwargs.get("backup_path"),
            cfgfile=kwargs.get("cfgfile"),
            debug=kwargs.get("debug", False),
            xheaders=True,
        )

        self.cache = CacheManager(**parse_cache_config_options({
            'cache.type': 'file',
            'cache.data_dir': '/tmp/cache/data',
            'cache.lock_dir': '/tmp/cache/lock'
        }))

        self.tp_lookup = TemplateLookup(directories=[settings['template_path']],
                                        default_filters=['decode.utf8'],
                                        input_encoding='utf-8',
                                        output_encoding='utf-8',
                                        encoding_errors='replace',
                                        module_directory="/tmp")


        self.db = scoped_session(sessionmaker(bind=server.db_engine, autocommit=False, autoflush=False))

        self.logging = logging.getLogger('app:logging')

        self.init_permit()

        permit.add_route(cyclone.web.StaticFileHandler,
                         r"/backup/download/(.*)",
                         u"下载数据",
                         u"系统管理",
                         handle_params={"path": settings['backup_path']},
                         order=1.0405)

        cyclone.web.Application.__init__(self, permit.all_handlers, **settings)

    def init_permit(self):
        conn = self.db()
        oprs = conn.query(models.TraOperator)
        for opr in oprs:
            if opr.operator_type > 0:
                for rule in self.db.query(models.TraOperatorRule).filter_by(operator_name=opr.operator_name):
                    permit.bind_opr(rule.operator_name, rule.rule_path)
            elif opr.operator_type == 0:  # 超级管理员授权所有
                permit.bind_super(opr.operator_name)


class PortalServer(object):
    
    def __init__(self,config, db_engine=None):
        self.config = config
        self.db_engine = db_engine
        self.init_config()
        self.init_timezone()
        print self.cfgfile
        self.web_factory = Application(
            server=self,
            debug=self.debug,
            api_secret=self.secret,
            backup_path=self.backup_path,
            cfgfile=self.cfgfile
        )
        
    def init_config(self):
        self.logfile = self.config.get('admin','logfile')
        self.cfgfile = self.config.get('DEFAULT', 'cfgfile')
        self.secret = os.environ.get("SECRET", self.config.get('DEFAULT', 'secret'))
        self.timezone = os.environ.get("TIMEZONE", self.config.get('DEFAULT', 'tz') or 'CST-8')
        self.debug = self.config.getboolean('DEFAULT','debug')
        self.port = self.config.getint('admin', 'port')
        self.host = self.config.has_option('admin', 'host') \
                    and self.config.get('admin', 'host') or '0.0.0.0'

        self.backup_path = self.config.get("database","backup_path")

        # update aescipher
        utils.aescipher.setup(self.secret)
        self.encrypt = utils.aescipher.encrypt
        self.decrypt = utils.aescipher.decrypt
    
    def init_timezone(self):
        try:
            os.environ["TZ"] = self.timezone
            time.tzset()
        except:pass


    def run_normal(self):
        log.startLogging(sys.stdout)
        log.msg('admin web server listen %s'%self.host)
        reactor.listenTCP(self.port, self.web_factory,interface=self.host)


 
def run(config, db_engine=None):
    print 'running portal server...'
    portal = PortalServer(config, db_engine)
    portal.run_normal()
    reactor.run()

